#nullable disable
using ERPBackend.Models;
using ERPBackend.Data;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using System;

namespace ERPBackend.Services
{
    public class EBOMService : IEBOMService
    {
        private readonly ApplicationDbContext _context;

        public EBOMService(ApplicationDbContext context)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context));
        }

        public async Task<IEnumerable<EBOM>> GetAllEBOMsAsync()
        {
            return await _context.EBOMs
                .Include(e => e.Material)
                .Include(e => e.EBOMItems)
                    .ThenInclude(b => b.Material)
                .ToListAsync();
        }

        public async Task<EBOM?> GetEBOMByIdAsync(int id)
        {
            return await _context.EBOMs
                .Include(e => e.Material)
                .Include(e => e.EBOMItems)
                    .ThenInclude(b => b.Material)
                .FirstOrDefaultAsync(e => e.Id == id);
        }

        public async Task<EBOM?> GetEBOMByCodeAndVersionAsync(string bomCode, string version)
        {
            return await _context.EBOMs
                .Include(e => e.Material)
                .Include(e => e.EBOMItems)
                    .ThenInclude(b => b.Material)
                .FirstOrDefaultAsync(e => e.BomCode == bomCode && e.Version == version);
        }

        public async Task<IEnumerable<EBOM>> GetEBOMsByMaterialIdAsync(int materialId)
        {
            return await _context.EBOMs
                .Include(e => e.Material)
                .Include(e => e.EBOMItems)
                    .ThenInclude(b => b.Material)
                .Where(e => e.MaterialId == materialId)
                .ToListAsync();
        }

        public async Task<IEnumerable<EBOM>> SearchEBOMsAsync(string bomCode, string materialName, string status)
        {
            var query = _context.EBOMs
                .Include(e => e.Material)
                .Include(e => e.EBOMItems)
                    .ThenInclude(b => b.Material)
                .AsQueryable();

            if (!string.IsNullOrEmpty(bomCode))
            {
                query = query.Where(e => e.BomCode.Contains(bomCode));
            }

            if (!string.IsNullOrEmpty(materialName))
            {
                query = query.Where(e => e.MaterialName.Contains(materialName) || e.Material.MaterialName.Contains(materialName));
            }

            if (!string.IsNullOrEmpty(status))
            {
                query = query.Where(e => e.Status == status);
            }

            return await query.ToListAsync();
        }

        public async Task<EBOM> CreateEBOMAsync(EBOM ebom)
        {
            // 验证物料是否存在
            var materialExists = await _context.Materials.AnyAsync(m => m.Id == ebom.MaterialId);
            if (!materialExists)
            {
                throw new ArgumentException("Invalid material id");
            }

            // 验证BOM明细
            if (ebom.EBOMItems == null || !ebom.EBOMItems.Any())
            {
                throw new ArgumentException("BOM must have at least one item");
            }

            // 验证BOM明细中的物料是否存在并计算总用量
            foreach (var item in ebom.EBOMItems)
            {
                var materialExistsInItem = await _context.Materials.AnyAsync(m => m.Id == item.MaterialId);
                if (!materialExistsInItem)
                {
                    throw new ArgumentException($"Invalid material id in BOM item: {item.MaterialId}");
                }

                // 计算总用量（考虑损耗）
                item.TotalQuantity = item.Quantity * (1 + item.ScrapRate / 100);
            }

            // 设置默认状态为草稿
            if (string.IsNullOrEmpty(ebom.Status))
            {
                ebom.Status = "草稿";
            }

            // 设置创建时间
            ebom.CreatedTime = DateTime.Now;

            _context.EBOMs.Add(ebom);
            await _context.SaveChangesAsync();

            return ebom;
        }

        public async Task<bool> UpdateEBOMAsync(EBOM ebom)
        {
            // 验证BOM是否存在
            var existingEBOM = await _context.EBOMs.FindAsync(ebom.Id);
            if (existingEBOM == null)
            {
                return false;
            }

            // 验证物料是否存在
            var materialExists = await _context.Materials.AnyAsync(m => m.Id == ebom.MaterialId);
            if (!materialExists)
            {
                throw new ArgumentException("Invalid material id");
            }

            // 验证BOM明细
            if (ebom.EBOMItems == null || !ebom.EBOMItems.Any())
            {
                throw new ArgumentException("BOM must have at least one item");
            }

            // 移除旧的BOM明细
            var oldBOMItems = await _context.EBOMItems.Where(b => b.BomId == ebom.Id).ToListAsync();
            _context.EBOMItems.RemoveRange(oldBOMItems);

            // 验证新的BOM明细中的物料是否存在并计算总用量
            foreach (var item in ebom.EBOMItems)
            {
                var materialExistsInItem = await _context.Materials.AnyAsync(m => m.Id == item.MaterialId);
                if (!materialExistsInItem)
                {
                    throw new ArgumentException($"Invalid material id in BOM item: {item.MaterialId}");
                }

                // 计算总用量（考虑损耗）
                item.TotalQuantity = item.Quantity * (1 + item.ScrapRate / 100);
                item.BomId = ebom.Id;
            }

            // 更新BOM信息
            existingEBOM.BomCode = ebom.BomCode;
            existingEBOM.MaterialId = ebom.MaterialId;
            existingEBOM.MaterialName = ebom.MaterialName;
            existingEBOM.MaterialSpecification = ebom.MaterialSpecification;
            existingEBOM.Description = ebom.Description;
            existingEBOM.Remark = ebom.Remark;
            existingEBOM.UpdatedBy = ebom.UpdatedBy;
            existingEBOM.UpdatedTime = DateTime.Now;

            // 添加新的BOM明细
            _context.EBOMItems.AddRange(ebom.EBOMItems);

            return await _context.SaveChangesAsync() > 0;
        }

        public async Task<bool> DeleteEBOMAsync(int id)
        {
            var ebom = await _context.EBOMs.FindAsync(id);
            if (ebom == null)
            {
                return false;
            }

            // 删除相关的BOM明细
            var bomItems = await _context.EBOMItems.Where(b => b.BomId == id).ToListAsync();
            _context.EBOMItems.RemoveRange(bomItems);

            // 删除相关的BOM变更记录
            var bomChanges = await _context.EBOMChanges.Where(b => b.BomId == id).ToListAsync();
            _context.EBOMChanges.RemoveRange(bomChanges);

            // 删除BOM
            _context.EBOMs.Remove(ebom);

            return await _context.SaveChangesAsync() > 0;
        }

        public async Task<bool> ApproveEBOMAsync(int id, int approvedBy)
        {
            var ebom = await _context.EBOMs.FindAsync(id);
            if (ebom == null)
            {
                return false;
            }

            ebom.Status = "已审核";
            ebom.ApprovedBy = approvedBy;
            ebom.ApprovedTime = DateTime.Now;
            ebom.UpdatedBy = approvedBy;
            ebom.UpdatedTime = DateTime.Now;

            return await _context.SaveChangesAsync() > 0;
        }

        public async Task<bool> EnableEBOMAsync(int id, int enabledBy)
        {
            var ebom = await _context.EBOMs.FindAsync(id);
            if (ebom == null)
            {
                return false;
            }

            ebom.Status = "已启用";
            ebom.UpdatedBy = enabledBy;
            ebom.UpdatedTime = DateTime.Now;

            return await _context.SaveChangesAsync() > 0;
        }

        public async Task<bool> DisableEBOMAsync(int id, int disabledBy)
        {
            var ebom = await _context.EBOMs.FindAsync(id);
            if (ebom == null)
            {
                return false;
            }

            ebom.Status = "已禁用";
            ebom.UpdatedBy = disabledBy;
            ebom.UpdatedTime = DateTime.Now;

            return await _context.SaveChangesAsync() > 0;
        }

        public async Task<EBOM> CreateNewVersionAsync(int originalBomId, string newVersion, int createdBy, string changeReason)
        {
            // 获取原始BOM
            var originalBom = await _context.EBOMs
                .Include(e => e.EBOMItems)
                .FirstOrDefaultAsync(e => e.Id == originalBomId);

            if (originalBom == null)
            {
                throw new ArgumentException("Original BOM not found");
            }

            // 检查新版本号是否已存在
            var versionExists = await _context.EBOMs.AnyAsync(e => e.BomCode == originalBom.BomCode && e.Version == newVersion);
            if (versionExists)
            {
                throw new ArgumentException($"Version {newVersion} already exists for BOM {originalBom.BomCode}");
            }

            // 创建新的BOM
            var newBom = new EBOM
            {
                BomCode = originalBom.BomCode,
                MaterialId = originalBom.MaterialId,
                MaterialName = originalBom.MaterialName,
                MaterialSpecification = originalBom.MaterialSpecification,
                Version = newVersion,
                Status = "草稿",
                Description = originalBom.Description,
                CreatedBy = createdBy,
                CreatedTime = DateTime.Now,
                Remark = originalBom.Remark
            };

            // 复制BOM明细
            foreach (var item in originalBom.EBOMItems)
            {
                newBom.EBOMItems.Add(new EBOMItem
                {
                    MaterialId = item.MaterialId,
                    MaterialName = item.MaterialName,
                    Specification = item.Specification,
                    Unit = item.Unit,
                    Quantity = item.Quantity,
                    ScrapRate = item.ScrapRate,
                    TotalQuantity = item.TotalQuantity,
                    Position = item.Position,
                    Remark = item.Remark
                });
            }

            // 添加新BOM
            _context.EBOMs.Add(newBom);

            // 添加变更记录
            var bomChange = new EBOMChange
            {
                BomId = originalBomId,
                OldVersion = originalBom.Version,
                NewVersion = newVersion,
                ChangeType = "新增",
                ChangeReason = changeReason,
                ChangedBy = createdBy,
                ChangedTime = DateTime.Now
            };

            _context.EBOMChanges.Add(bomChange);

            await _context.SaveChangesAsync();

            return newBom;
        }
    }
}